home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------;
- ; CONFIG.CTL - Allows you to dynamically change your CONFIG.SYS ;
- ; configuration at boot time. Add DEVICE = CONFIG.CTL [m] ;
- ; to your CONFIG.SYS just ahead of the first command you wish ;
- ; to be able to modify. m is seconds CONFIG.CTL will pause ;
- ; for a keystroke before booting normally. m defaults to zero. ;
- ; Add DEVICE = CONFIG.END after the last command you wish to be ;
- ; able to modify. CONFIG.END is a dummy device and must appear ;
- ; in CONFIG.SYS in order for CONFIG.CTL to operate. ;
- ; Requires MASM 2.0 or later. Remember to EXE2BIN ;
- ; CONFIG.CTL 1.0 (C) 1988 Ziff Communications Co.
- ;----------------------------------------------------------------;
- _TEXT SEGMENT PUBLIC 'CODE'
- ASSUME CS:_TEXT,DS:_TEXT
- ASSUME ES:_TEXT,SS:_TEXT
- ORG 0H
-
- ;************* DEVICE_HEADER *************;
- POINTER DD -1
- ATTRIBUTE DW 1000000000000000B
- DEVICE_STAG DW STRATEGY
- DEVICE_INT DW INTERRUPT
- DEVICE_NAME DB "CONFIGURE"
-
- CR EQU 13
- LF EQU 10
- CTRL_Z EQU 26
- SPACE EQU 32
- COMMA EQU 44
- FORWARD_SLASH EQU 47
- BOX EQU 254
- ;-------------------------;
- REQUEST_HEADER STRUC
-
- HEADER_LENGTH DB ?
- UNIT_CODE DB ?
- COMMAND_CODE DB ?
- STATUS DW ?
- RESERVED DQ ?
-
- REQUEST_HEADER ENDS
-
- DONE EQU 0000000100000000B ;Status codes.
- UNKNOWN EQU 1000000000000011B
- ;-------------------------;
- INIT STRUC
-
- HEADER DB (TYPE REQUEST_HEADER) DUP(?)
- UNITS DB ?
- ENDING_OFFSET DW ?
- ENDING_SEGMENT DW ?
- ARGUMENTS_OFF DW ?
- ARGUMENTS_SEG DW ?
-
- INIT ENDS
-
- REQUEST_OFFSET DW ?
- REQUEST_SEG DW ?
-
- ;-----------------------------------------------------------------------------;
- ; The only task of the strategy is to save the pointer to the request header. ;
- ;-----------------------------------------------------------------------------;
- STRATEGY PROC FAR
-
- MOV CS:REQUEST_OFFSET,BX ;Request header address is
- MOV CS:REQUEST_SEG,ES ; passed in ES:BX.
- RET
-
- STRATEGY ENDP
-
- ;------------------------------------------------------------------------;
- ; The interrupt procedure will be called immediately after the strategy. ;
- ;------------------------------------------------------------------------;
- INTERRUPT PROC FAR
-
- PUSH AX ;Responsible for all registers.
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DS
- PUSHF
-
- MOV DS,CS:REQUEST_SEG ;Retrieve request header pointer.
- MOV BX,CS:REQUEST_OFFSET
-
- OR STATUS[BX],DONE ;Tell DOS we are done.
- CMP COMMAND_CODE[BX],0 ;Is it INIT command?
- JZ MAKE_STACK ;If yes, do our stuff.
- OR STATUS[BX],UNKNOWN ;Else, exit with confused
- JMP SHORT UNKNOWN_EXIT ; message to DOS.
-
- MAKE_STACK: MOV CX,SS ;Save DOS stack.
- MOV DX,SP
- MOV AX,CS
- CLI
- MOV SS,AX ;Make new stack.
- MOV SP,0FFFEH
- STI
- PUSH CX ;Save old stack pointers on new.
- PUSH DX
-
- PUSH ES ;Save rest of registers.
- PUSH SI
- PUSH DI
- PUSH BP
-
- CALL INITIALIZE ;Go do our stuff.
-
- POP BP ;Restore registers.
- POP DI
- POP SI
- POP ES
-
- POP DX ;Restore old DOS stack.
- POP CX
- CLI
- MOV SS,CX
- MOV SP,DX
- STI
-
- UNKNOWN_EXIT: POPF ;Restore rest of registers.
- POP DS
- POP DX
- POP CX
- POP BX
- POP AX
- RET ;Far return back to DOS.
-
- INTERRUPT ENDP
-
- CONFIG_CTL_END LABEL WORD
-
- ;************* END OF RESIDENT PORTION *************;
-
- BUFFER_SEGMENT DW ? ;CONFIG.SYS buffer segment
- BUFFER_START DW ? ; and offset.
- BUFFER_END DW ? ;CONFIG.END address.
- END_FLAG DB 0 ;CONFIG.END found flag.
-
- CONFIG_END DB "DCONFIG.END"
- CONFIG_END_LEN EQU $ - CONFIG_END
-
- DELAY_MSG DB CR,LF,LF,"Press any key if you wish to modify the "
- DB "CONFIG.SYS configuration.",CR,LF
- DB "Press Esc for quick bypass of CONFIG.CTL.",CR,LF,LF,"$"
- NOT_FOUND_MSG DB "DEVICE=CONFIG.END has to be added as a terminating "
- DB CR,LF,"command in CONFIG.SYS before CONFIG.CTL can "
- DB "function.",CR,LF,"Press and key to continue.$"
- ;--------------------------;
- NORMAL EQU 07H ;Screen attributes.
- INVERSE EQU 70H
-
- HEADING LABEL BYTE
- DB "CONFIG.CTL 1.0 (C) 1988 Ziff Communications Co.",CR,LF
- DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF
-
- DB "Press F1 to toggle active state of highlighted command.",CR,LF
- DB "You may optionally edit a highlighted command.",CR,LF
- DB "Press F2 to accept changes and exit.",CR,LF
- DB "Press Esc to abort changes and exit.",CR,LF
- DB "Note: Permanent changes are not made to the CONFIG.SYS file.$"
- ;----------------------------;
- STRING_MAX EQU 80
- DISPLAY_MAX EQU 67
- LAST_RECORD EQU -1
-
- DATA_RECORD STRUC
-
- COMMAND DB STRING_MAX DUP (?)
- STRING_LENGTH DW ?
- ADDRESS DW ? ;Command string address start.
-
- DATA_RECORD ENDS
-
- ROW_START EQU 9
- COL_START EQU 12
-
- CODES DB "CBQDXFSKL" ;DOS command codes.
- CODES_LENGTH EQU $ - CODES ;For example "C" = BREAK
-
- COMMAND_TABLE DB "BREAK" ,5 DUP (SPACE), "BUFFERS" ,3 DUP (SPACE)
- DB "COUNTRY" ,3 DUP (SPACE), "DEVICE" ,4 DUP (SPACE)
- DB "FCBS" ,6 DUP (SPACE), "FILES" ,5 DUP (SPACE)
- DB "SHELL" ,5 DUP (SPACE), "STACKS" ,4 DUP (SPACE)
- LAST_COMMAND DB "LASTDRIVE" ,1 DUP (SPACE)
- TABLE_END EQU $
- COMMAND_SIZE EQU TABLE_END - LAST_COMMAND
-
- INACTIVE DB "INACTIVE" ,2 DUP (SPACE)
-
- HIGH_BIT EQU 10000000B
- ESC_KEY EQU 01H
- ENTER_KEY EQU 1CH
- F1_KEY EQU 3BH
- F2_KEY EQU 3CH
- BACKSPACE_KEY EQU 0EH
- UP_ARROW_KEY EQU 48H
- DN_ARROW_KEY EQU 50H
- LT_ARROW_KEY EQU 4BH
- RT_ARROW_KEY EQU 4DH
- HOME_KEY EQU 47H
- END_KEY EQU 4FH
- PG_UP_KEY EQU 49H
- PG_DN_KEY EQU 51H
- BS EQU 8
-
- DISPATCH_KEY DB F1_KEY, BACKSPACE_KEY, UP_ARROW_KEY, DN_ARROW_KEY
- DB LT_ARROW_KEY, RT_ARROW_KEY, HOME_KEY, END_KEY
- DB PG_UP_KEY, PG_DN_KEY, ENTER_KEY
- KEY_COUNT EQU $ - DISPATCH_KEY
-
- DISPATCH_TABLE DW F1, BACKSPACE, UP_ARROW, DN_ARROW
- DW LT_ARROW, RT_ARROW, HOME, END_CURSOR
- DW PG_UP, PG_DN, DN_ARROW
- DISPATCH_END EQU $ - 2
-
- ;------------------------------------------;
- ; INPUT ;
- ; DS:BX points to request header. ;
- ; ;
- ; All registers destroyed. ;
- ;------------------------------------------;
- INITIALIZE PROC NEAR
-
- MOV ENDING_OFFSET[BX],OFFSET CONFIG_CTL_END
- MOV ENDING_SEGMENT[BX],CS ;Resident portion setup.
-
- MOV AX,ARGUMENTS_SEG[BX] ;Retrieve CONFIG.SYS buffer
- MOV ES,AX ; pointers from INIT table.
- MOV BX,ARGUMENTS_OFF[BX]
- PUSH CS ;Point to our data.
- POP DS
- MOV BUFFER_SEGMENT,ES ;And save the segment.
- CLD
- ;------------------------------------;
- ; Parse CONFIG.CTL second parameter. ;
- ;------------------------------------;
- XOR BP,BP ;Use BP to store seconds.
- NEXT_NUMBER: MOV AL,ES:[BX] ;Retrieve a byte.
- INC BX ;Point to next byte.
- CMP AL,CR ;If carriage return of linefeed,
- JZ FIND_END ; found end of parameter.
- CMP AL,LF
- JZ FIND_END
- SUB AL,"0" ;ASCII to binary.
- JC NEXT_NUMBER ;If not between 0 and 9, skip.
- CMP AL,9
- JA NEXT_NUMBER
- CBW ;Convert to word.
- XCHG AX,BP ;Swap old and new number.
- MOV CX,10 ;Shift to left by multiplying
- MUL CX ; last entry by ten.
- ADD BP,AX ;Add new number and store in BP.
- JMP SHORT NEXT_NUMBER
- ;-----------------------------------------------------------------------;
- ; Search for dummy CONFIG.END device as signature of end of buffer. ;
- ; If found, replace "D" device code with "Z" unrecognized command code. ;
- ;-----------------------------------------------------------------------;
- FIND_END: MOV BUFFER_START,BX ;Save start of first command.
- NEXT_BYTE: MOV SI,OFFSET CONFIG_END ;Point to CONFIG.END.
- MOV DI,BX ;Point to current buffer pos.
- MOV CX,CONFIG_END_LEN ;Is it CONFIG.END?
- REPZ CMPSB
- JZ FOUND_END ;If yes, found end.
- INC BX ;Else, increment buff pos.
- CMP BX,0FFFFH - CONFIG_END_LEN ;End of segment?
- JNZ NEXT_BYTE ;If no, continue.
- JMP SHORT PAUSE ;Else, give up search.
-
- FOUND_END: MOV END_FLAG,1 ;Flag that we found CONFIG.END.
- MOV BYTE PTR ES:[BX],"Z" ;"Z" out CONFIG.END command.
- DEC BX ;Adjust to buffer end
- MOV BUFFER_END,BX ; and store.
- ;-------------------------------------------------------------;
- ; See if user pressed key requesting CONFIG.SYS modification. ;
- ;-------------------------------------------------------------;
- PAUSE: CALL CK_KEY ;Key pressed?
- JNZ ATTENTION ;If yes, give attention.
- MOV CX,BP ;Else, retrieve second delay.
- JCXZ INIT_END ;If zero, we're done.
- MOV DX,OFFSET DELAY_MSG ;Else, display "Press key for
- CALL PRINT_STRING ; service" message.
-
- WAIT_A_SEC: CALL DELAY ;Delay a second.
- POLL_KEY: CALL CK_KEY ;Key pressed?
- JNZ ATTENTION ;If yes, give attention.
- LOOP WAIT_A_SEC ;Else, continue waiting until
- JMP SHORT INIT_END ; time out.
- ;--------------------------------------------------------------;
- ; If keystroke other than ESC was pressed and CONFIG.END dummy ;
- ; device found, then we're in business; otherwise exit.
- ;--------------------------------------------------------------;
- ATTENTION: PUSH AX ;Save key press.
- CALL CLEAR_KEY ;Clear keyboard buffer.
- POP AX ;Retrieve key press.
- CMP AH,ESC_KEY ;Was is Esc?
- JZ INIT_END ;If yes, we're done.
- CMP END_FLAG,1 ;Else, did we find CONFIG.END?
- JZ CONTINUE ;If yes, continue.
- MOV DX,OFFSET NOT_FOUND_MSG ;Else, Display CONFIG.END not
- CALL PRINT_STRING ; found message.
- CALL GET_KEY ;Wait for keystroke so it can be
- JMP SHORT INIT_END ; read and then exit.
-
- CONTINUE: CALL BUSINESS ;Do our thing.
-
- INIT_END: RET ;Exit.
- INITIALIZE ENDP
- ;--------------------------------------------;
- ; INPUT ;
- ; DS = CS ;
- ; ES = CONFIG.SYS command buffer segment. ;
- ; ;
- ; All registers destroyed. ;
- ;--------------------------------------------;
- BUSINESS PROC NEAR
-
- CALL CLS ;Clear the screen.
- MOV DX,OFFSET HEADING ;Display heading messages.
- CALL PRINT_STRING
- ;----------------------------------------------------------------------------;
- ; Retrieve the commands from CONFIG.SYS buffer and place them in our buffer. ;
- ;----------------------------------------------------------------------------;
- MOV SI,BUFFER_START ;Point to start of commands.
- MOV DX,BUFFER_END ;DX = end of buffer.
- MOV BX,OFFSET DATA_STORAGE ;Point to our storage.
- PUSH CS ;Destination segment our data.
- POP ES
- PUSH BUFFER_SEGMENT ;Source segment CONFIG.SYS
- POP DS ; command buffer.
-
- NEXT_COMMAND: CMP SI,DX ;End of buffer?
- JAE COMMAND_END ;If yes, done here.
- LODSB ;Get a byte.
- CMP AL,CR ;Carriage return or linefeed?
- JZ NEXT_COMMAND ;If yes, delimiter; skip.
- CMP AL,LF
- JZ NEXT_COMMAND
- PUSH AX ;Else, command code character.
- DEC SI ;Adjust pointer.
- MOV ES:ADDRESS[BX],SI ;Save starting address.
- MOV DI,BX ;Point to our storage.
- CALL RETRIEVE ;Go retrieve the command string.
- POP AX ;Retrieve command code.
- CMP AL,"Z" ;Was it unrecognized "Z" ?
- JZ NEXT_COMMAND ;If yes, skip.
- DEC CX ;Else, adjust string length less
- DEC CX ; code and ending linefeed.
- JCXZ NEXT_COMMAND ;Null string? If yes, skip.
- MOV ES:STRING_LENGTH[BX],CX ;Else, store length.
- ADD BX,TYPE DATA_RECORD ;Point to next storage record.
- JMP SHORT NEXT_COMMAND ;Get next command.
-
- COMMAND_END: PUSH CS ;Back to our data segment.
- POP DS
- MOV COMMAND[BX],LAST_RECORD ; -1 as end of data signature.
- CMP BX,OFFSET DATA_STORAGE ;Were there any commands?
- JZ BUSINESS_END ;If no, done here.
- ;--------------------------------------------------;
- ; Display the commands and let the user edit them. ;
- ;--------------------------------------------------;
- CALL DISPLAY
- CALL EDIT
- JC BUSINESS_END ;If carry, Esc was pressed.
- ;----------------------------------------------------------;
- ; Place the edited commands back in the CONFIG.SYS buffer. ;
- ;----------------------------------------------------------;
- MOV BX,OFFSET DATA_STORAGE ;Point to CONFIG.SYS buffer
- PUSH BUFFER_SEGMENT ; as destination.
- POP ES
-
- STORE_COMMAND: CMP COMMAND[BX],LAST_RECORD ;Is it the last record?
- JZ BUSINESS_END ;If yes, we're all done.
- TEST COMMAND[BX],HIGH_BIT ;Is command inactive?
- JZ REPLACE_DATA ;If no, OK.
- MOV COMMAND[BX],"Z" ;Else, replace with "Z".
- REPLACE_DATA: MOV SI,BX ;Point to command string.
- MOV DI,ADDRESS[BX] ;Point to destination address.
- CALL REPLACE ;Replace the string in buffer.
- ADD BX,TYPE DATA_RECORD ;Point to next record.
- JMP SHORT STORE_COMMAND ;And store it.
-
- BUSINESS_END: CALL CLS ;Exit with clean slate.
- RET
- BUSINESS ENDP
- ;---------------------------------------;
- ; INPUT ;
- ; DS:SI points to CONFIG.SYS buffer. ;
- ; ES:DI points to our storage. ;
- ; ;
- ; OUTPUT ;
- ; SI and DI at end of string. ;
- ; CX = string length include one byte ;
- ; for command code and one byte for ;
- ; CR or LF. ASCIIZ is stripped. ;
- ; ;
- ; AX destroyed. ;
- ;---------------------------------------;
- RETRIEVE PROC NEAR
-
- XOR CX,CX ;Zero in string length counter.
- NEXT_RETRIEVE: LODSB ;Get a byte.
- OR AL,AL ;If it's ASCIIZ zero,
- JZ NEXT_RETRIEVE ; skip it.
- STOSB ;Else, store it.
- INC CX ;Increment count.
- CMP AL,CR ;If terminating carriage return
- JZ RETRIEVE_END ; or linefeed, we're done.
- CMP AL,LF
- JNZ NEXT_RETRIEVE
- RETRIEVE_END: RET
-
- RETRIEVE ENDP
- ;--------------------------------------;
- ; INPUT ;
- ; DS:SI points to our storage. ;
- ; ES:DI points to CONFIG.SYS buffer. ;
- ; BX = current record. ;
- ; ;
- ; OUTPUT ;
- ; ASCIIZ is reinserted in string. ;
- ; SI and DI at end of string. ;
- ; ;
- ; AX, CX, DX, BP destroyed. ;
- ;--------------------------------------;
- REPLACE PROC NEAR
-
- MOV CX,STRING_LENGTH[BX] ;Retrieve string length.
- INC CX ;Include command code byte.
- MOV BP,-1 ;ASCIIZ flag.
- XOR DX,DX ;Leading space flag.
- NEXT_REPLACE: LODSB ;Get a byte.
- CMP AL,"a" ;Capitalize.
- JB CK_LEADING
- CMP AL,"z"
- JA CK_LEADING
- AND AL,5FH
-
- CK_LEADING: CMP AL,SPACE ;Is it a leading space?
- JNZ CK_ADD_ZERO ;If no, check if zero time.
- CMP DX,1 ;If command only thing stored
- JZ NEXT_REPLACE ; so far, then it's leading.
-
- CK_ADD_ZERO: CMP BP,-1 ;Have we stored a zero yet?
- JNZ CK_CR_LF ;If yes, check CR and LF.
- CMP AL,SPACE ;Else, if it's delimiting
- JZ ASCIIZ ; space, comma, slash, CR or LF
- CMP AL,COMMA ; then store a terminating
- JZ ASCIIZ ; right in front of it.
- CMP AL,FORWARD_SLASH
- JZ ASCIIZ
- CMP AL,CR
- JZ ASCIIZ
- CMP AL,LF
- JNZ STORE_BYTE
-
- ASCIIZ: XCHG AX,BP ;Swap special character.
- XOR AX,AX ;Store the zero.
- STOSB ;Retrieve the character and
- XCHG AX,BP ; zero in BP as flag.
-
- CK_CR_LF: CMP AL,CR ;If CR or LF we're done here.
- JZ PAD_SPACES
- CMP AL,LF
- JZ PAD_SPACES
-
- STORE_BYTE: STOSB ;Store the byte.
- INC DX ;Increment count.
- LOOP NEXT_REPLACE
-
- PAD_SPACES: JCXZ REPLACE_END ;If end of string, done.
- MOV AL,SPACE ;Else, move leading spaces
- REP STOSB ; to end of string.
- REPLACE_END: RET
- REPLACE ENDP
- ;------------------------------------------;
- ; Display the commands on the screen. ;
- ; All registers destroyed. ;
- ;------------------------------------------;
- DISPLAY PROC NEAR
-
- MOV BP,OFFSET DATA_STORAGE ;Point to data storage.
- MOV DH,ROW_START ;Point to first display row.
-
- NEXT_DISPLAY: XOR DL,DL ;Column zero.
- CALL SET_CURSOR ;Set cursor position.
- CMP COMMAND[BP],LAST_RECORD ;Is it the last record?
- JZ DISPLAY_END ;If yes, done here.
- CALL DECODE ;Else, decode the command.
- MOV AL,"=" ;Add quotes and a space.
- CALL WRITE_TTY
- MOV AL,SPACE
- CALL WRITE_TTY
- MOV SI,BP ;Point to command string.
- INC SI
- MOV CX,STRING_LENGTH[BP] ;Retrieve the string length.
- NEXT_ARGUMENT: LODSB ;Display the command.
- CALL WRITE_TTY
- LOOP NEXT_ARGUMENT
- ADD BP,TYPE DATA_RECORD ;Point to next record.
- INC DH ;Next cursor row.
- CMP DH,25 ;Is it row 25?
- JNZ NEXT_DISPLAY ;If no, continue.
-
- DISPLAY_END: RET
- DISPLAY ENDP
- ;-----------------------------------------;
- ; INPUT ;
- ; BP points to command. ;
- ; ;
- ; OUTPUT ;
- ; The command is decoded and displayed. ;
- ; ;
- ; AX, CX, SI and DI destroyed. ;
- ;-----------------------------------------;
- DECODE PROC NEAR
-
- MOV SI,OFFSET INACTIVE ;Assume command inactive.
- MOV AL,COMMAND[BP] ;Retrieve command.
- TEST AL,HIGH_BIT ;Is it marked inactive?
- JNZ FOUND_COMMAND ;If yes, assumed right.
- MOV DI,OFFSET CODES ;Else, point to codes.
- MOV CX,CODES_LENGTH ;Number of codes.
- REPNZ SCASB ;Search for match.
- MOV SI,OFFSET TABLE_END ;Point to interpolation table.
- INC CX ;Adjust count.
- FIND_COMMAND: SUB SI,COMMAND_SIZE ;Point to appropriate command.
- LOOP FIND_COMMAND
-
- FOUND_COMMAND: MOV CX,COMMAND_SIZE ;Command string length.
- DISPLAY_CMD: LODSB ;Display it.
- CALL WRITE_TTY
- LOOP DISPLAY_CMD
- RET
-
- DECODE ENDP
- ;----------------------------------;
- ; OUTPUT ;
- ; Carry flag = 0 if good edit. ;
- ; Carry flag = 1 if edit abort. ;
- ; ;
- ; All registers destroyed. ;
- ;----------------------------------;
- EDIT PROC NEAR
-
- MOV BP,OFFSET DATA_STORAGE ;Point to data storage.
- MOV DH,ROW_START ;Point to first row.
- MOV BL,INVERSE ;Highlight the first command.
- CALL HIGHLIGHT_BAR ;Return with DI = 1; first char.
-
- NEXT_KEY: CALL GET_KEY ;Get a keystroke.
- CMP AH,ESC_KEY ;Is it ESC?
- JZ NO_CHANGE ;If yes, exit with no change.
- CMP AH,F2_KEY ;Is it F2?
- JZ EDIT_END ;If yes, exit with changes.
- CMP AL,BS ;Is it backspace?
- JZ FUNCTION ;If yes, function.
- CMP AL,CR ;Is it carriage return?
- JZ FUNCTION ;If yes, function.
- CMP AH,F1_KEY ;Is it F1 or above?
- JAE FUNCTION ;If yes, function.
-
- ASCII: CMP AL,SPACE ;Is it space or above?
- JB NEXT_KEY ;If no, skip.
- CMP DI,STRING_LENGTH[BP] ;Else, are we at end of field?
- JA NEXT_KEY ;If yes, skip.
- MOV COMMAND[BP+DI],AL ;Else, store character.
- INC DI ;Point to next storage.
- INC DL ;Increment cursor column.
- CALL WRITE_TTY ;Write the character to screen.
- JMP SHORT NEXT_KEY ;Get next keystroke.
-
- FUNCTION: MOV AL,AH ;Scan code in AL.
- MOV CX,KEY_COUNT ;Count of active functions.
- PUSH DI ;Preserve DI.
- MOV DI,OFFSET DISPATCH_KEY ;Point to active keys.
- REPNZ SCASB ;Scan for match.
- POP DI ;Retrieve DI.
- JNZ NEXT_KEY ;If no match, next key.
- MOV SI,OFFSET DISPATCH_END ;Else, point to dispatch table.
- SHL CX,1 ;Convert to word offset.
- SUB SI,CX ;Point to appropriate procedure
- CALL DS:[SI] ; and go do it.
- JMP SHORT NEXT_KEY ;Get next keystroke.
-
- NO_CHANGE: STC
- EDIT_END: RET
-
- EDIT ENDP
- ;----------------------------------------------------------------------------;
- ; The following are the active function, arrow and backspace key procedures. ;
- ;----------------------------------------------------------------------------;
- F1 PROC NEAR
-
- PUSH DI ;Preserve DI and DX.
- PUSH DX
- XOR DL,DL ;Column zero.
- CALL SET_CURSOR ;Set cursor.
- XOR COMMAND[BP],HIGH_BIT ;Toggle active state.
- CALL DECODE ;Decode the command.
- POP DX ;Restore cursor position.
- CALL SET_CURSOR
- POP DI ;Restore DI.
- RET
-
- F1 ENDP
- ;------------------------------;
- BACKSPACE PROC NEAR
-
- CMP DI,1 ;Are we already at first char?
- JZ BACKSPACE_END ;If yes, skip.
- DEC DL ;Else, decrement cursor
- DEC DI ; and character storage position.
- MOV COMMAND[BP+DI],SPACE ;Store a space.
- MOV AL,BS ;Write a backspace, space and
- CALL WRITE_TTY ;backspace to screen.
- MOV AL,SPACE
- CALL WRITE_TTY
- MOV AL,BS
- CALL WRITE_TTY
- BACKSPACE_END: RET
-
- BACKSPACE ENDP
- ;------------------------------;
- UP_ARROW PROC NEAR
-
- CMP BP,OFFSET DATA_STORAGE ;Are we already at top row?
- JZ UP_ARROW_END ;If yes, skip.
- MOV BL,NORMAL ;Else, return to normal
- CALL HIGHLIGHT_BAR ; attribute current row.
- SUB BP,TYPE DATA_RECORD ;Move up a record.
- DEC DH ;Move cursor up one.
- MOV BL,INVERSE ;Display line in inverse video.
- CALL HIGHLIGHT_BAR
- UP_ARROW_END: RET
-
- UP_ARROW ENDP
- ;------------------------------;
- DN_ARROW PROC NEAR
-
- CMP COMMAND[BP+TYPE DATA_RECORD],LAST_RECORD
- JZ DN_ARROW_END
- CMP DH,24 ;If last record already or
- JZ DN_ARROW_END ; bottom of screen, skip.
- MOV BL,NORMAL ;Else, return current row to
- CALL HIGHLIGHT_BAR ; normal.
- ADD BP,TYPE DATA_RECORD ;Go down a record.
- INC DH ;And down a row.
- MOV BL,INVERSE ;Display the line inverse video.
- CALL HIGHLIGHT_BAR
- DN_ARROW_END: RET
-
- DN_ARROW ENDP
- ;------------------------------;
- LT_ARROW PROC NEAR
-
- CMP DI,1 ;Are we already first positon?
- JZ LT_ARROW_END ;If yes, skip.
- DEC DI ;Else, decrement storage position
- DEC DL ; and cursor position.
- CALL SET_CURSOR
- LT_ARROW_END: RET
-
- LT_ARROW ENDP
- ;------------------------------;
- RT_ARROW PROC NEAR
-
- CMP DI,STRING_LENGTH[BP] ;Are we already end of string?
- JA RT_ARROW_END ;If yes, skip.
- INC DI ;Else, increment storage position
- INC DL ; and cursor position.
- CALL SET_CURSOR
- RT_ARROW_END: RET
-
- RT_ARROW ENDP
- ;------------------------------;
- HOME PROC NEAR
-
- MOV DI,1 ;Home storage position
- MOV DL,COL_START ; and cursor.
- CALL SET_CURSOR
- RET
-
- HOME ENDP
- ;------------------------------;
- END_CURSOR PROC NEAR
-
- MOV DI,STRING_LENGTH[BP] ;Retrieve string length.
- MOV CX,DI
- MOV DL,CL
- ADD DL,COL_START ;Add to starting column.
- INC DI ;Adjust.
- CALL SET_CURSOR ;Set cursor.
- RET
-
- END_CURSOR ENDP
- ;------------------------------;
- PG_DN PROC NEAR
-
- MOV BL,NORMAL ;Current postion back to normal.
- CALL HIGHLIGHT_BAR
- NEXT_PG_DN: CMP COMMAND[BP+TYPE DATA_RECORD],LAST_RECORD
- JZ PAGE_END
- ADD BP,TYPE DATA_RECORD ;If not already last position,
- INC DH ; go to it.
- JMP SHORT NEXT_PG_DN
- PAGE_END: MOV BL,INVERSE ;And display it in inverse video.
- CALL HIGHLIGHT_BAR
- RET
-
- PG_DN ENDP
- ;------------------------------;
- PG_UP PROC NEAR
-
- MOV BL,NORMAL ;Restore current position to
- CALL HIGHLIGHT_BAR ; normal.
- MOV BP,OFFSET DATA_STORAGE ;Move to top command.
- MOV DH,ROW_START ;And cursor position.
- MOV BL,INVERSE ;And highlight.
- CALL HIGHLIGHT_BAR
- RET
-
- PG_UP ENDP
- ;------------------------------------------;
- ; INPUT ;
- ; BL = attribute. ;
- ; BP points to current command. ;
- ; ;
- ; OUTPUT ;
- ; DI = 1 (First storage position.) ;
- ; DL = cursor column start. ;
- ; ;
- ; CX, SI destroyed. ;
- ;------------------------------------------;
- HIGHLIGHT_BAR PROC NEAR
-
- MOV CX,STRING_LENGTH[BP] ;Retrieve string length.
- MOV SI,BP ;Point to command.
- INC SI ;Adjust.
- MOV DL,COL_START ;Point to first position.
- HIGHLIGHT: CALL SET_CURSOR ;Set the cursor.
- LODSB
- PUSH CX ;Preserve CX.
- MOV CX,1
- MOV AH,9 ;Write char/attribute.
- INT 10H
- INC DL ;Increment cursor postion.
- POP CX
- LOOP HIGHLIGHT
- MOV DL,COL_START ;Point to first position again.
- CALL SET_CURSOR ;Set cursor.
- MOV DI,1 ;Return with DI = first storage.
- RET
-
- HIGHLIGHT_BAR ENDP
- ;---------------------------------------;
- ; The following are support procedures. ;
- ;---------------------------------------;
- WRITE_TTY PROC NEAR
-
- MOV AH,0EH ;Write TTY via BIOS.
- INT 10H
- RET
-
- WRITE_TTY ENDP
- ;------------------------------;
- SET_CURSOR PROC NEAR
-
- XOR BH,BH ;Enter with DX = cursor postion.
- MOV AH,2 ;Set cursor position via BIOS.
- INT 10H
- RET
-
- SET_CURSOR ENDP
- ;------------------------------;
- CLS PROC NEAR
-
- MOV AH,0FH ;Get current video mode.
- INT 10H
- XOR AH,AH ;Set current video mode.
- INT 10H ;Result is a clear screen.
- RET
-
- CLS ENDP
- ;------------------------------;
- DELAY PROC NEAR
-
- PUSH DS ;Preserve data segment.
- MOV AX,40H ;Point to BIOS data segment.
- MOV DS,AX
- MOV AX,DS:[6CH] ;Retrieve timer low.
- ADD AX,18 ;Add 18 counts per second.
- NEXT_COUNT: MOV DX,DS:[6CH] ;Retrieve timer low.
- CMP DX,AX ;Have we timed out?
- JNZ NEXT_COUNT ;If not, wait until second up.
- POP DS ;Restore data segment.
- RET
-
- DELAY ENDP
- ;------------------------------;
- GET_KEY: MOV AH,0 ;Retrieve keystroke via BIOS.
- INT 16H
- RET
-
- CK_KEY: MOV AH,1 ;Check for keystroke via BIOS.
- INT 16H
- RET
-
- CLEAR_IT: CALL GET_KEY
- CLEAR_KEY: CALL CK_KEY ;Clear keyboard buffer.
- JNZ CLEAR_IT
- RET
- ;------------------------------;
- PRINT_STRING: MOV AH,9 ;Print string via DOS.
- INT 21H
- RET
- ;------------------------------;
- DATA_STORAGE EQU $
-
- _TEXT ENDS
- END
-